package calao.storage;

public final class RangeCondition extends FieldCondition {

	static interface Comparator {
		boolean lessThan(Number n1, Number n2);
		boolean greaterThan(Number n1, Number n2);
	}

	final Comparator comparator;
	
	Number minValue;
	Number maxValue;
	
	public RangeCondition(Field<? extends Number> field)
	{
		super(field);
		switch (field.type.enumValue) {
		case INTEGER: 
		case LONG: 
		case SHORT: 
			comparator = new Comparator() {
				public boolean greaterThan(Number n1, Number n2) {
					return n1.longValue()>n2.longValue();
				}
				public boolean lessThan(Number n1, Number n2) {
					return n1.longValue()<n2.longValue();
				}
			};
			break;
		case DOUBLE: 
			comparator = new Comparator() {
				public boolean greaterThan(Number n1, Number n2) {
					return n1.doubleValue()>n2.doubleValue();
				}
				public boolean lessThan(Number n1, Number n2) {
					return n1.doubleValue()<n2.doubleValue();
				}
			};
			break;
		default:
			throw new Error();
		}
	}
	
	public RangeCondition(Field<? extends Number> field, Number minValue)
	{
		this(field);
		setMinValue(minValue);
	}

	public RangeCondition(Field<? extends Number> field, Number minValue, Number maxValue)
	{
		this(field, minValue);
		setMaxValue(maxValue);
	}

	private Number toFieldValue(Number number)
	{
		switch (field.type.enumValue) {
		case SHORT: return number.shortValue();
		case INTEGER: return number.intValue();
		case LONG: return number.longValue();
		case DOUBLE: return number.doubleValue();
		default:
			throw new Error();
		}
	}

	public void setMinValue(Number value)
	{
		minValue = value!=null? toFieldValue(value) : null;
	}

	public void setMaxValue(Number value)
	{
		maxValue = value!=null? toFieldValue(value) : null;
	}

	public boolean matches(Object value)
	{
		try {
			Number n = (Number)value;
			if (minValue!=null) {
				if (n==null) return false;
				if (comparator.lessThan(n, minValue)) return false;
			}
			if (maxValue!=null) {
				if (n==null) return false;
				if (comparator.greaterThan(n, maxValue)) return false;
			}
			return true;
		}
		catch (ClassCastException e) {
			return false;
		}
	}
		
	public Number getMinValue()
	{
		return minValue;
	}
	
	public Number getMaxValue()
	{
		return maxValue;
	}
	
	public boolean hasMinValue()
	{
		return minValue!=null;
	}
		
	public boolean hasMaxValue()
	{
		return maxValue!=null;
	}

}
